from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
from django.contrib import auth
from django.contrib.auth.models import User
from users.models import Label, URL, AllTimeScore, TodayBestMatch
from django.http import Http404
from django.core.mail import send_mail
from yahoo.search.image import ImageSearch
import random
import threading

user_list = []
player_gameinfo = {}
off_limit = {}

class GameInfo:
    partner = ""
    label_dict = {}
    order_list = []
    cur_url_id = 0
    pass_url_id = 0
    def __init__(self, partner, label_dict, order_list, cur_url_id):
        self.partner = partner
        self.label_dict = label_dict
        self.order_list = order_list
        self.cur_url_id = cur_url_id

class Position:
    x1 = 0
    y1 = 0
    x2 = 0
    y2 = 0
    def __init__(self, x1, y1, x2, y2):
        self.x1 = x1
        self.y1 = y1
        self.x2 = x2
        self.y2 = y2

class LabelInfo:
    isPass = False
    isMatch = False
    label_list = []
    pos_list = []
    match_word = ""
    match_pos = Position(0,0,0,0)
    def __init__(self, isPass, isMatch, label_list, pos_list):
        self.isPass = isPass
        self.isMatch = isMatch
        self.label_list = label_list
        self.pos_list = pos_list

class ResultInfo:
    url = ""
    domain = ""
    word_list = []
    pos = Position(0,0,0,0)
    width = 0
    height = 0
    def __init__(self, url, domain, word_list, pos, width, height):
        self.url = url
        self.domain = domain
        self.word_list = word_list
        self.pos = pos
        self.width = width
        self.height = height

def login(request):
    if request.method == 'GET':
        return render_to_response('login.xhtml', {'user': request.user})
    # print "login"
    user_name = request.POST.get('username', '')
    password = request.POST.get('password', '')
    user = auth.authenticate(username=user_name, password=password)
    if user_name != '' and  password != '' and user is not None and user.is_active:
        auth.login(request, user)
        return HttpResponseRedirect('/home/')
    else:
        return render_to_response('login.xhtml')

def check_login(request, user_name, password):
    #print "check_login"
    user = auth.authenticate(username=user_name, password=password)
    if user is not None and user.is_active:
        return HttpResponse("Success")
    else:
        return HttpResponse("Failure")

def home(request):
    #print request.user
    all_time_top9 = AllTimeScore.objects.order_by('-score')[0:9]
    today_best_match9 = TodayBestMatch.objects.order_by('-score')[0:9]
    return render_to_response('home.xhtml', {'user': request.user, 'all_time_top': all_time_top9, 'today_best_match': today_best_match9})

def logout(request):
    auth.logout(request)
    return HttpResponseRedirect('/login/')

def register(request):
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        confirmpassword = request.POST.get('confirmpassword', '')
        email = request.POST.get('email', '')
        if password == confirmpassword:
            user = User.objects.create_user(username, email, password)
            user.save()
            user = auth.authenticate(username=username, password=password)
            auth.login(request, user)
            return HttpResponseRedirect('/home/')
        else:
            return HttpResponse("Confirm password wrong.")
    else:
        return render_to_response("register.xhtml")

def is_user_exist(request, username):
    isExist = False
    user_list = User.objects.filter(username=username)
    if len(user_list) == 1:
        isExist = True
    return HttpResponse(isExist)

def start_game(request):
    global player_gameinfo
    username = request.user.username

    print username
    semaphore = threading.BoundedSemaphore()
    if semaphore.acquire(): # decrements the counter
        global user_list
        if not len(user_list):
            user_list.append(username)
            return HttpResponse("no_user_exists")
        elif user_list[0] != username:
            user_choose = user_list[0]
            del user_list[0]

            print username
            ##### choose a url randomly #####
            url_choose = get_url_limit(request)
            url_id = url_choose[0]

            print url_id

            global player_gameinfo
            player_gameinfo[username] = GameInfo(user_choose, {}, [url_id], url_id)
            player_gameinfo[user_choose] = GameInfo(username, {}, [url_id], url_id)
            (player_gameinfo[username].label_dict)[url_id] = LabelInfo(False, False, [], [])
            (player_gameinfo[user_choose].label_dict)[url_id] = LabelInfo(False, False, [], [])

            return HttpResponse("Success")
        semaphore.release() # increments the counter

def has_match(request):
    global player_gameinfo
    if (player_gameinfo.has_key(request.user.username)):
        return HttpResponse("Success")
    return HttpResponse("has_not_match")

def game(request):
    global player_gameinfo
    url_id = player_gameinfo[request.user.username].cur_url_id
    url_choose = URL.objects.get(id=url_id)
    url = url_choose.url
    width = url_choose.width
    height = url_choose.height
    if width >= height:
        return render_to_response("game.xhtml", {'user': request.user, 'url': url, 'width': width, 'height': 0})
    else:
        return render_to_response("game.xhtml", {'user': request.user, 'url': url, 'width': 0, 'height': height})

def check(request, key_word):
    print 'check here with ' + key_word
    global player_gameinfo
    username = request.user.username
    user_choose = player_gameinfo[username].partner
    cur_url_id = player_gameinfo[username].cur_url_id
    ##### add key word to self list #####
    player_gameinfo[username].label_dict[cur_url_id].label_list.append(key_word)
    ##### get key word list from partner #####
    key_word_list = player_gameinfo[user_choose].label_dict[cur_url_id].label_list
    for word in key_word_list:
        if key_word == word:
            print key_word + ' match'
            ##### update label frequency #####
            try:
                print 'check label'
                print key_word
                print cur_url_id
#                label = Label.objects.get(label=key_word)
                label = Label.objects.get(label=key_word, url=URL.objects.get(id=cur_url_id))
#                label = Label.objects.get(url_id=int(cur_url_id))
                if label.url.id == cur_url_id:
                    print 'exist label'
                    label.frequency = label.frequency + 1
                    label.save()
                else:
                    print 'no label'
                    new_label = Label(label=key_word, frequency=1, url_id=(cur_url_id))
                    new_label.save()
#                label = Label.objects.get(label=key_word, url_id=cur_url_id)
#                print label
#                if label.url_id == cur_url_id:
#                    print label
#                label.frequency = label.frequency + 1
#                label.save()
#                    print 'label exist'
#                else:
#                    print label.url_id
#                    new_label = Label(label=key_word, frequency=1, url_id=cur_url_id)
#                    new_label.save()
            except Label.DoesNotExist:
                print 'no label'
                new_label = Label(label=key_word, frequency=1, url_id=cur_url_id)
                new_label.save()
#            else:
#                print 'else'
#            except Label.MultipleObjectsReturned:
#                label_again
#                print 'm'
            ##### choose a url not used #####
            print cur_url_id
            id_url_limit = get_url_limit(request)
            url_id = id_url_limit[0]
            url = id_url_limit[1]
            off_limit_list = id_url_limit[2]
            width = id_url_limit[3]
            height = id_url_limit[4]
            print id_url_limit
            ##### new url_id #####
            player_gameinfo[username].order_list.append(url_id)
            player_gameinfo[username].cur_url_id = url_id
            ##### initialize a new label list #####
            (player_gameinfo[username].label_dict)[url_id] = LabelInfo(False, False, [])
            (player_gameinfo[user_choose].label_dict)[url_id] = LabelInfo(False, False, [])
            ##### add new off_limit_word_list to global off_limit #####
            global off_limit
            if (off_limit.has_key(url_id) == False):
                off_limit[url_id] = off_limit_list
            print 'match here'
            ##### match now #####
            (player_gameinfo[username].label_dict)[cur_url_id].isMatch = True
            (player_gameinfo[user_choose].label_dict)[cur_url_id].isMatch = True
            return HttpResponse('match##' + url + '##' + '#'.join(off_limit_list) + '##' + str(width) + '##' + str(height))
    return HttpResponse('not_match##' + str(len(key_word_list)))

def check_background(request):
    print 'check background ' + request.user.username
    global player_gameinfo
    username = request.user.username
    my_cur_url_id = player_gameinfo[username].cur_url_id;
    user_choose = player_gameinfo[username].partner
    cur_url_id = player_gameinfo[user_choose].cur_url_id
    key_word_list = player_gameinfo[user_choose].label_dict[cur_url_id].label_list
    ##### check match #####
    print (player_gameinfo[username].label_dict)[my_cur_url_id].isMatch
    if (player_gameinfo[username].label_dict)[my_cur_url_id].isMatch:
        urlModel = URL.objects.get(id=cur_url_id)
        url = urlModel.url
        off_limit_list = off_limit[cur_url_id]
        ##### set x1, y1, x2, y2 #####
        match_pos = 0
        print 'set pos in background'
        print my_cur_url_id
        print player_gameinfo[user_choose].label_dict[my_cur_url_id].label_list
        print len(player_gameinfo[user_choose].label_dict[my_cur_url_id].pos_list)
#        for each_pos in player_gameinfo[user_choose].label_dict[my_cur_url_id].pos_list:
#            print 'check position with ' + username
#            print each_pos.x1
#            print each_pos.x1
#            print each_pos.x1
#            print each_pos.x1
        for each_label in player_gameinfo[user_choose].label_dict[my_cur_url_id].label_list:
            if each_label == player_gameinfo[user_choose].label_dict[my_cur_url_id].match_word:
                pos_choose = player_gameinfo[user_choose].label_dict[my_cur_url_id].pos_list[match_pos]
                print pos_choose.x1
                print pos_choose.y1
                print pos_choose.x2
                print pos_choose.y2
            else:
                match_pos = match_pos + 1
        player_gameinfo[username].label_dict[my_cur_url_id].match_pos = pos_choose
        ##### update url_id_list and cur_url_id #####
        player_gameinfo[username].cur_url_id = player_gameinfo[user_choose].cur_url_id
        player_gameinfo[username].order_list.append(cur_url_id)
        print 'match##' + url + '##' + '#'.join(off_limit_list) + '##' + str(urlModel.width) + '##' + str(urlModel.height)
        return HttpResponse('match##' + url + '##' + '#'.join(off_limit_list) + '##' + str(urlModel.width) + '##' + str(urlModel.height))
    ##### not match then check pass #####
    elif player_gameinfo[username].pass_url_id != 0 and (player_gameinfo[username].label_dict)[player_gameinfo[username].pass_url_id].isPass:
        print 'pass'
        if (player_gameinfo[user_choose].label_dict)[player_gameinfo[user_choose].pass_url_id].isPass == True:
            print username + ' pass'
            if len(player_gameinfo[username].order_list) == len(player_gameinfo[user_choose].order_list):
                print username + ' jump equal'
                player_gameinfo[username].pass_url_id = my_cur_url_id
                ##### choose a url not used #####
                id_url_limit = get_url_limit(request)
                url_id = id_url_limit[0]
                url = id_url_limit[1]
                off_limit_list = id_url_limit[2]
                width = id_url_limit[3]
                height = id_url_limit[4]
                ##### new url_id #####
                player_gameinfo[username].order_list.append(url_id)
                player_gameinfo[username].cur_url_id = url_id
                ##### initialize a new label list #####
                (player_gameinfo[username].label_dict)[url_id] = LabelInfo(False, False, [], [])
                (player_gameinfo[user_choose].label_dict)[url_id] = LabelInfo(False, False, [], [])
                ##### add new off_limit_word_list to global off_limit #####
                global off_limit
                if (off_limit.has_key(url_id) == False):
                    off_limit[url_id] = off_limit_list
            elif len(player_gameinfo[username].order_list) <= len(player_gameinfo[user_choose].order_list):
                print username + ' jump less'
                cur_url_id = player_gameinfo[user_choose].cur_url_id
                player_gameinfo[username].order_list.append(cur_url_id)
                player_gameinfo[username].cur_url_id = cur_url_id
                player_gameinfo[username].pass_url_id = cur_url_id
                player_gameinfo[user_choose].pass_url_id = cur_url_id
                urlModel = URL.objects.get(id=cur_url_id)
                url = urlModel.url
                off_limit_list = off_limit[cur_url_id]
                width = urlModel.width
                height = urlModel.height
            print 'pass##' + url + '##' + '#'.join(off_limit_list)
            return HttpResponse('pass##' + url + '##' + '#'.join(off_limit_list) + '##' + str(width) + '##' + str(height))
        else:
            print username + ' wait for' + user_choose
            return HttpResponse('wait')
    elif (player_gameinfo[user_choose].label_dict)[my_cur_url_id].isPass == True:
        print 'pass'
        return HttpResponse('not_pass')
    else:
        print 'not match'
        ##### not match && not pass
        print 'not_match##' + str(len(key_word_list))
        return HttpResponse('not_match##' + str(len(player_gameinfo[user_choose].label_dict[my_cur_url_id].label_list)))

def check_pass(request):
    global player_gameinfo
    username = request.user.username
    user_choose = player_gameinfo[username].partner
    my_cur_url_id = player_gameinfo[username].cur_url_id;
#    print username + ' pass true'
    player_gameinfo[username].pass_url_id = my_cur_url_id
    player_gameinfo[user_choose].pass_url_id = my_cur_url_id
    (player_gameinfo[username].label_dict)[my_cur_url_id].isPass = True
#    print '??????'
    return HttpResponse('finish')

def get_first_off_limit_list(request):
    global player_gameinfo
    username = request.user.username
    first_url_id = player_gameinfo[username].order_list[0]
    print first_url_id
    if off_limit.has_key(first_url_id):
        first_off_limit_list = off_limit[first_url_id]
        return HttpResponse('#'.join(first_off_limit_list))
    else:
        total_frequency = 0
        off_limit_rate = 0
        off_limit_list = []
        for each_label in Label.objects.filter(url=first_url_id):
            total_frequency += each_label.frequency
        for each_label in Label.objects.filter(url=first_url_id):
            if (each_label.frequency >= total_frequency * off_limit_rate):
                off_limit_list.append(each_label.label)
        off_limit[first_url_id] = off_limit_list
        return HttpResponse('#'.join(off_limit_list))

def get_url_limit(request):
    global player_gameinfo
    username = request.user.username
    url_limit = []
    search_probability = 1
    random_double = random.random()
    if random_double >= search_probability:
        while(True):
            urlModel = URL.objects.all()[random.randint(0, len(URL.objects.all()) - 1)]
            url_id = urlModel.id
            url = urlModel.url
            width = urlModel.width
            height = urlModel.height
            if (player_gameinfo.has_key(username) and url_id not in player_gameinfo[username].label_dict.keys()) or player_gameinfo.has_key(username) == False:
                total_frequency = 0
                off_limit_rate = 0
                off_limit_list = []
                for each_label in Label.objects.filter(url=url_id):
                    total_frequency += each_label.frequency
                for each_label in Label.objects.filter(url=url_id):
                    if (each_label.frequency >= total_frequency * off_limit_rate):
                        off_limit_list.append(each_label.label)
                break
    else:
        while(True):
            search = ImageSearch(app_id="YahooDemo", query="hello", results = 10)
            res_choose = random.randint(0,9)
#            print 'random ' + str(res_choose)
            res_pos = 0
            for res in search.parse_results():
                if res_choose == res_pos:
                    url = res.Url
                    width = res.Width
                    height = res.Height
                    print url
                    break
                else:
                    res_pos = res_pos + 1
            try:
                urlModel = URL.objects.get(url=url,width=width,height=height)
#                print 'url exist'
                url_id = URL.objects.get(url=url,width=width,height=height).id
                total_frequency = 0
                off_limit_rate = 0
                off_limit_list = []
                for each_label in Label.objects.filter(url=url_id):
                    total_frequency += each_label.frequency
                for each_label in Label.objects.filter(url=url_id):
                    if (each_label.frequency >= total_frequency * off_limit_rate):
                        off_limit_list.append(each_label.label)
            except URL.DoesNotExist:
#                print 'url not exist'
                urlModel = URL(url=url, width=width, height=height)
                urlModel.save()
#                print urlModel.id
                url_id = URL.objects.get(url=url).id
#                print url_id
                off_limit_list = []
            if (player_gameinfo.has_key(username) and url_id not in player_gameinfo[username].label_dict.keys()) or player_gameinfo.has_key(username) == False:
                break

    url_limit.append(url_id)
    url_limit.append(url)
    url_limit.append(off_limit_list)
    url_limit.append(width)
    url_limit.append(height)
#    print url_limit
    return url_limit

def get_game_result(request, score):
    global player_gameinfo
    username = request.user.username
    user_choose = player_gameinfo[username].partner
    score = int(score)
    ##### update personal score #####
    my_score = AllTimeScore.objects.get(username=username)
    my_score.score = my_score.score + score
    my_score.save()
    ##### update match score #####
    try:
        match = TodayBestMatch.objects.get(user1=username, user2=user_choose)
    except TodayBestMatch.DoesNotExist:
        ##### no match before #####
        try:
            match = TodayBestMatch.objects.get(user1=user_choose, user2=username)
        except TodayBestMatch.DoesNotExist:
            my_match = TodayBestMatch(user1=username, user2=user_choose, score=score)
            my_match.save()
        else:
            if match.score < score:
                match.score = score
                match.save()
    else:
        ##### match ever #####
        if match.score < score:
            match.score = score
            match.save()
    ##### get return data #####
    all_time_top5 = AllTimeScore.objects.order_by('-score')[0:5]
    today_best_match5 = TodayBestMatch.objects.order_by('-score')[0:5]
    result_list = []
    for url_id in player_gameinfo[username].order_list:
        urlModel = URL.objects.get(id=url_id)
        url = urlModel.url
        width = urlModel.width
        height = urlModel.height
        pos = player_gameinfo[username].label_dict[url_id].match_pos
        print 'reduce pos ' + username
        if width > height:
            pos = reduce_pos(pos, width)
            height = 0
        else:
            pos = reduce_pos(pos, height)
            width = 0
        result_list.append(ResultInfo(url, get_domain(url),  player_gameinfo[user_choose].label_dict[url_id].label_list, pos, width, height))
    return render_to_response('result.xhtml', {'user': username, 'partner': user_choose, 'score': score, 'all_time_top': all_time_top5, 'today_best_match': today_best_match5, 'result_list': result_list})

def get_partial_label(request):
    global player_gameinfo
    username = request.user.username
    partial_label_list = []
    for url_id in player_gameinfo[username].order_list:
        urlModel = URL.objects.get(id=url_id)
        url = urlModel.url
        width = urlModel.width
        height = urlModel.height
        pos = player_gameinfo[username].label_dict[url_id].match_pos
        print 'reduce pos ' + username
        if width > height:
            pos = reduce_pos(pos, width)
            height = 0
        else:
            pos = reduce_pos(pos, height)
            width = 0
        partial_label_list.append(str(pos.x1) + '#' + str(pos.y1) + '#' + str(pos.x2) + '#' + str(pos.y2))
    print '##'.join(partial_label_list)
    return HttpResponse('##'.join(partial_label_list))
    


def reduce_pos(pos, area):
    size = 150
#    return Position(int(pos.x1)*150/int(area), int(pos.y1)*150/int(area), int(pos.x2)*150/int(area), int(pos.y2)*150/int(area))
    return Position(int(pos.x1)/2, int(pos.y1)/2, int(pos.x2)/2, int(pos.y2)/2)

def get_domain(http_url):
    for i in range(0, len(http_url)-1):
        if i > 6 and http_url[i] == '/':
            end = i
            break
    print end
    print http_url[7:8]
    print http_url[7:end]
    return http_url[7:end]

def check_with_pic(request, key_word, x1, y1, x2, y2):
    print 'check here with pic ' + key_word + ' ' + request.user.username
    global player_gameinfo
    username = request.user.username
    user_choose = player_gameinfo[username].partner
    cur_url_id = player_gameinfo[username].cur_url_id
    ##### set partial label #####
    print x1
    print y1
    print x2
    print y2
    (player_gameinfo[username].label_dict)[cur_url_id].pos_list.append(Position(x1,y1,x2,y2))
    print 'add position by ' + username + ' ' + str(len((player_gameinfo[username].label_dict)[cur_url_id].pos_list))
    print 'position by ' + user_choose + ' ' + str(len(player_gameinfo[user_choose].label_dict[cur_url_id].pos_list))
    ##### add key word to self list #####
    player_gameinfo[username].label_dict[cur_url_id].label_list.append(key_word)
    print cur_url_id
    print player_gameinfo[username].label_dict[cur_url_id].pos_list
    ##### get key word list from partner #####
    key_word_list = player_gameinfo[user_choose].label_dict[cur_url_id].label_list
    for word in key_word_list:
        if key_word == word:
            print key_word + ' match'
            ##### update label frequency #####
            try:
                print key_word
                print cur_url_id
                label = Label.objects.get(label=key_word, url=URL.objects.get(id=cur_url_id))
                if label.url.id == cur_url_id:
                    label.frequency = label.frequency + 1
                    label.save()
                else:
                    new_label = Label(label=key_word, frequency=1, url_id=(cur_url_id))
                    new_label.save()
            except Label.DoesNotExist:
                new_label = Label(label=key_word, frequency=1, url_id=cur_url_id)
                new_label.save()
            ##### set x1, y1, x2, y2 #####
            match_pos = 0
            for each_label in player_gameinfo[user_choose].label_dict[cur_url_id].label_list:
                if each_label == key_word:
                    pos_choose = player_gameinfo[user_choose].label_dict[cur_url_id].pos_list[match_pos]
                    print pos_choose.x1
                    print pos_choose.y1
                    print pos_choose.x2
                    print pos_choose.y2
                else:
                    match_pos = match_pos + 1
            player_gameinfo[username].label_dict[cur_url_id].match_pos = pos_choose
            player_gameinfo[username].label_dict[cur_url_id].match_word = key_word
            player_gameinfo[user_choose].label_dict[cur_url_id].match_word = key_word
            ##### get new url id #####
            id_url_limit = get_url_limit(request)
            url_id = id_url_limit[0]
            url = id_url_limit[1]
            off_limit_list = id_url_limit[2]
            width = id_url_limit[3]
            height = id_url_limit[4]
            print id_url_limit
            ##### new url_id #####
            player_gameinfo[username].order_list.append(url_id)
            player_gameinfo[username].cur_url_id = url_id
            ##### initialize a new label list #####
            (player_gameinfo[username].label_dict)[url_id] = LabelInfo(False, False, [], [])
            (player_gameinfo[user_choose].label_dict)[url_id] = LabelInfo(False, False, [], [])
            ##### add new off_limit_word_list to global off_limit #####
            global off_limit
            if (off_limit.has_key(url_id) == False):
                off_limit[url_id] = off_limit_list
            print 'match here'
            ##### match now #####
            (player_gameinfo[username].label_dict)[cur_url_id].isMatch = True
            (player_gameinfo[user_choose].label_dict)[cur_url_id].isMatch = True
            return HttpResponse('match##' + url + '##' + '#'.join(off_limit_list) + '##' + str(width) + '##' + str(height))
    return HttpResponse('not_match##' + str(len(key_word_list)))

def recover(request):
    if request.method == 'GET':
        return render_to_response('recover.xhtml')
    username = request.POST.get('username', '')
    if User.objects.filter(username=username):
        email = User.objects.get(username=username).email
        send_mail('ESP Game Password Recovery', 'Hello, ' + username
                + '. Click here to reset your password: http://127.0.0.1:8000/reset_password/' + username + '/',
                'angelbless2012@gmail.com', [email], fail_silently=True)
        return HttpResponseRedirect('/home/')
    else:
        return HttpResponseRedirect('/recover/')

def reset_password(request, username):
    if request.method == 'GET':
        if User.objects.filter(username=username):
            return render_to_response('resetpasswd.xhtml', {'user': username})
        else:
            raise Http404
    password = request.POST.get('password', '')
    confirmpassword = request.POST.get('confirmpassword', '')
    if User.objects.filter(username=username):
        user = User.objects.get(username=username)
        if password == confirmpassword:
            user.set_password(password)
            user.save()
            user = auth.authenticate(username=username, password=password)
            if username != '' and  password != '' and user is not None and user.is_active:
                auth.login(request, user)
                return HttpResponseRedirect('/home/')
    else:
        raise Http404